home *** CD-ROM | disk | FTP | other *** search
- /*...................... ADAPT.C .................. 6-3-94 ....*/
- /* This program demonstrates Adaptive Color Palette generation.*/
- /* It reads True Color (24 bit per pixel) TARGA images and */
- /* converts them to 8 bit palette images. It also writes out */
- /* the converted image as an 8 bit per pixel Palette Color TIFF*/
- /* image. */
- /*.............................................................*/
-
- #include<malloc.h>
- #include<stdlib.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <io.h>
- #include<conio.h>
- #include <math.h>
- #include<tiff.h>
- #include<vsa.h>
-
- /*.............................................................*/
- /* Define type struct CUBE first, needed later! */
- /*.............................................................*/
- struct CUBE {
- unsigned x0;
- unsigned y0;
- unsigned z0;
- unsigned x1; // Outside of cube volume!
- unsigned y1; // Outside of cube volume!
- unsigned z1; // Outside of cube volume!
- unsigned vol; // this is the volume of the cube;
- long r_avg; // this is the Average Red value for cube
- long g_avg; // this is the Average Green value for cube
- long b_avg; // this is the Average Blue value for cube
- long fsum; // this is the sum of frequencies in cube
- long cerr; // this is the NET color error for the cube
- float fom; // Figure Of Merit, Worthyness of cube split
- };
-
- /*.............................................................*/
- /* All of the function prototypes. */
- /*.............................................................*/
- int adaptive_lut(char *,unsigned char far *,
- unsigned char far *);
- int volume_hist(char *, unsigned char far *);
- void analyze_row(unsigned char far *, int, unsigned char far *);
- void bisect_cube(struct CUBE far *,struct CUBE far *);
- void gen_cube_color_stats(struct CUBE far *,
- unsigned char far *,int);
- void validate_cube(struct CUBE far *);
- void copy_cube(struct CUBE, struct CUBE far *);
- int add_cube_to_list(struct CUBE, int);
- int delete_cube_from_list(int, int);
- int move_cubes_to_lut(int, unsigned char far *,
- unsigned char far *);
- void assign_lut_to_colors(unsigned char far *, unsigned);
- void replace_pixel(unsigned char *, unsigned, unsigned char *);
- void set_adaptive_config(int, int, int);
- void get_adaptive_config(int far *, int far *, int far *);
- unsigned long read_tga_header(int, int *, int *, int *, int *);
- void true_color_lut(void);
-
- /*.............................................................*/
- /* Global variables which control the show. */
- /*.............................................................*/
- int ADPTV_MODE = 0; /*.. Default = 0 (Off) ..*/
- int ADPTV_NUM_COLORS = 256; /*.. Default = 256 ..*/
- int ADPTV_QUALITY = 50; /*.. Default = 50 ..*/
- struct CUBE CUBE_LIST[256];
-
- #define ADPTV_ASSIGN_MODE 0 /*.. This is experimental..*/
-
- void main()
- {
- char filename[80];
- int i,j,size,width,height,type,file_handle,orient, colors;
- unsigned char lut[768], rgb[3072], far *vhist;
- /*.............................................................*/
- /* Set up the Adaptive Palette controls and get the TARGA */
- /* image file name. */
- /*.............................................................*/
- set_adaptive_config(1,256,50);
- LOOP:
- printf("Input TARGA Image Filename: ");
- scanf("%s",filename);
- /*.............................................................*/
- /* Allocate memory for the Volume Histogram. Then run the */
- /* Adaptive Palette code to generate the adaptive palette. */
- /*.............................................................*/
- if(ADPTV_MODE)
- {
- printf("\n");
- printf("Please Wait, Computing Adaptive Color Palette.\n");
- printf("\n");
- if((vhist = (unsigned char far *)halloc(32768,1)) == NULL)
- {
- printf("Can't Allocate Memory for Histogram!\n");
- return;
- }
- colors = adaptive_lut(filename,vhist,lut);
- }
- /*.............................................................*/
- /* Set highest video resolution available. */
- /*.............................................................*/
- if(vsa_init(0x2105) != 0) /* 1024 x 768 x 256 */
- if(vsa_init(0x2103) != 0) /* 800 x 600 x 256 */
- if(vsa_init(0x2101) != 0) /* 640 x 480 x 256 */
- if(vsa_init(0x2100) != 0) /* 640 x 400 x 256 */
- {
- printf("Can't set VESA video mode\n");
- printf("Is VESA BIOS Extension TSR loaded?\n");
- return;
- }
- /*.............................................................*/
- /* Set up Color Palette either to Adaptive Palette or 8 bit RGB*/
- /*.............................................................*/
- if(ADPTV_MODE)
- vsa_write_color_block(0,colors,lut);
- else
- true_color_lut();
- /*.............................................................*/
- /* Open the TARGA file and get header info. */
- /*.............................................................*/
- if((file_handle = open(filename,O_BINARY | O_RDONLY)) == -1)
- return;
- read_tga_header(file_handle,&width,&height,&type,&orient);
- /*.............................................................*/
- /* Depending on orientation, read file out-top down or */
- /* bottom-up, replace 24 bit pixels with 8 bit palette indexes,*/
- /* and display on screen. */
- /*.............................................................*/
- if(orient == 32)
- for(j=0;j<height;j++)
- {
- read(file_handle,rgb,3*width);
- replace_pixel(rgb,width,vhist);
- vsa_raster_line(0,width-1,j,rgb);
- }
- else
- for(j=height-1;j>=0;j--)
- {
- read(file_handle,rgb,3*width);
- replace_pixel(rgb,width,vhist);
- vsa_raster_line(0,width-1,j,rgb);
- }
- /*.............................................................*/
- /* Close the image file and look for an ESC key to quit. */
- /* Otherwise, save new image as an 8 bit TIFF called */
- /* NEW.TIF and LOOP for experimentation with a different */
- /* input image files. */
- /*.............................................................*/
- if(ADPTV_MODE)
- hfree((unsigned char huge *)vhist);
- close(file_handle);
- if(getch() == 27)
- goto SKIP;
- tf_save_file(0,0,width-1,height-1,"new.tif");
- vsa_set_svga_mode(0x3);
- goto LOOP;
- SKIP:
- vsa_set_svga_mode(0x3);
- return;
- } /*..... End MAIN .....*/
-
-
- /*....................... READ_TGA_HEADER ....... 5-17-94 ....*/
- /* This routine parses through a TGA header and returns the */
- /* file offset in bytes to the first byte of pixel data. */
- /* It also returns image width, height, and type (type 2 is the*/
- /* uncompressed 24 bit image type). */
- /*.............................................................*/
- unsigned long read_tga_header(int handle, int *width,
- int *height, int *type,
- int *orientation)
- {
- unsigned long offset;
- unsigned char buff[18];
- read(handle,buff,18);
- offset = 18+buff[0];
- *type = buff[2];
-
- *width = *((unsigned *)buff + 6);
- *height = *((unsigned *)buff + 7);
- *orientation = buff[17];
- return offset;
- } /*.... END read_tga_header .....*/
-
-
- /*..................... ADAPTIVE_LUT ............ 5-31-94 .....*/
- /* This routine analyzes the True Color image that is */
- /* defined in the TARGA file called 'filename' and computes */
- /* an Adpative Color Palette which is an optimal selection of */
- /* the 256 colors for this particular image. Before calling */
- /* this routine, 'array' must have been allocated 32768 bytes!*/
- /* First a 32x32x32 volume histogram is computed. Then the */
- /* volume histogram "cube" is subdivide into up to 255 cubes */
- /* (color clusters) used in the image. One more cube in this */
- /* collection is always reserved for BLACK, in RGB space, */
- /* (this is done so that images which have few colors will */
- /* still get a good solid BLACK color in the CLUT). Finally */
- /* it assigns each one of the cubes to each one of the up to */
- /* 256 palette entries, and returns the new Color Look Up */
- /* Table in the 'color_array'. The function return value is */
- /* the number of colors in the 'color_array' and is always */
- /* equal to 256 for now (unused colors set to black). */
- /* Upon completion, the 32k elements of 'array' store the */
- /* palette index for their respective true color value (down */
- /* converted to 15 bits). */
- /*.............................................................*/
- int adaptive_lut(char *filename,unsigned char *array,
- unsigned char *color_array)
- {
- int num_cubes,num_vol,colors,most_cubes;
- struct CUBE cube,new_cube;
- most_cubes = ADPTV_NUM_COLORS-1;
- num_cubes = 0;
- VOLUME_HIST(filename,array);
- /*.............................................................*/
- /* Set up the number of cubes to be generated based on uniform */
- /* color VOLUME partitioning. Then, the rest of the cubes are */
- /* generated on COLOR ERROR minimizing criteria. */
- /*.............................................................*/
- num_vol = (ADPTV_QUALITY * most_cubes) / 100;
- /*.............................................................*/
- /* Initialize first cube. Get its color stats and put it in */
- /* cube list. */
- /*.............................................................*/
- if(most_cubes > 0)
- {
- cube.x0 = 0;
- cube.y0 = 0;
- cube.z0 = 0;
- cube.x1 = 32;
- cube.y1 = 32;
- cube.z1 = 32;
- gen_cube_color_stats(&cube,array,1);
- num_cubes = add_cube_to_list(cube,num_cubes);
- }
- /*.............................................................*/
- /* Subdivide color volume based on minimizing cube Volumes. */
- /* Do for 'num_vol' cubes. */
- /*.............................................................*/
- while(num_cubes < num_vol)
- {
- if(CUBE_LIST[0].vol <= 1)
- break;
- copy_cube(CUBE_LIST[0],&cube);
- bisect_cube(&cube,&new_cube);
- gen_cube_color_stats(&cube,array,1);
- gen_cube_color_stats(&new_cube,array,1);
- num_cubes = delete_cube_from_list(0,num_cubes);
- if(cube.fsum != 0)
- num_cubes = add_cube_to_list(cube,num_cubes);
- if(new_cube.fsum != 0)
- num_cubes = add_cube_to_list(new_cube,num_cubes);
- }
- /*.............................................................*/
- /* Continue subdividing color volume based on minimizing cube */
- /* color errors. Do for remaining cubes (up to */
- /* 'ADPTV_NUM_COLORS' - 1). */
- /*.............................................................*/
- while(num_cubes < most_cubes)
- {
- if(CUBE_LIST[0].vol <= 1)
- break;
- copy_cube(CUBE_LIST[0],&cube);
- bisect_cube(&cube,&new_cube);
- gen_cube_color_stats(&cube,array,2);
- gen_cube_color_stats(&new_cube,array,2);
- num_cubes = delete_cube_from_list(0,num_cubes);
- if(cube.fsum != 0)
- num_cubes = add_cube_to_list(cube,num_cubes);
- if(new_cube.fsum != 0)
- num_cubes = add_cube_to_list(new_cube,num_cubes);
- }
- /*.............................................................*/
- /* Add last cube which is BLACK. Force this cube to top of */
- /* list (via cube.fom = 1000000000) so that it will end up at */
- /* CLUT location 0. */
- /*.............................................................*/
- cube.x0 = 0;
- cube.y0 = 0;
- cube.z0 = 0;
- cube.x1 = 1;
- cube.y1 = 1;
- cube.z1 = 1;
- gen_cube_color_stats(&cube,array,1);
- cube.fom = 1000000000.0;
- num_cubes = add_cube_to_list(cube,num_cubes);
- /*.............................................................*/
- /* Finally, figure out the values for the Color Look Up table. */
- /*.............................................................*/
- colors = move_cubes_to_lut(num_cubes,array,color_array);
- return colors;
- } /*..... End adaptive_lut .....*/
-
-
- /*.......................... VOLUME_HIST ......... 5-31-94 ....*/
- /* This routine analyzes a True Color TARGA image file called */
- /* 'filename' and generates a 3D R-G-B Volume Histogram which */
- /* has 32 elements on a side (32 x 32 x 32). The histogram is */
- /* returned in 'vhist[]'. Each element of 'vhist[]' stores a */
- /* count from 0 to 255 which is the frequency of occurance for */
- /* that color in the image. The count "saturates" at 255. */
- /* ("That color" means the value indexing 'vhist') The value */
- /* indexing 'vhist' is a 15 bit color value whos 5 MSBs are */
- /* Red, then 5 bits Green and finally 5 LSBs of Blue. If the */
- /* image file is not found, this routine returns with a error */
- /* value of 1, else 0. */
- /*.............................................................*/
- int VOLUME_HIST(char *filename, unsigned char far *vhist)
- {
- unsigned i;
- int j,width,height,type,file_handle,orient;
- unsigned char rgb[3072];
- /*.............................................................*/
- /* Initialize 32x32x32 R-G-B historgram to all zeros. */
- /*.............................................................*/
- for(i=0;i<32768;i++)
- vhist[i] = 0;
- /*.............................................................*/
- /* Open the TARGA file and get header info. */
- /*.............................................................*/
- if((file_handle = open(filename,O_BINARY | O_RDONLY)) == -1)
- return 1;
- read_tga_header(file_handle,&width,&height,&type,&orient);
- /*.............................................................*/
- /* Read out pixels from TARGA file and process in */
- /* top down or bottom up order depending on orientation. */
- /*.............................................................*/
- if(orient == 32)
- for(j=0;j<height;j++)
- {
- read(file_handle,rgb,3*width);
- analyze_row(rgb,width,vhist);
- }
- else
- for(j=height-1;j>=0;j--)
- {
- read(file_handle,rgb,3*width);
- analyze_row(rgb,width,vhist);
- }
- /*.............................................................*/
- /* Close the image file. */
- /*.............................................................*/
- close(file_handle);
- return 0;
- } /*..... End VOLUME_HIST .....*/
-
-
- /*.................... ANALYZE_ROW ............... 5-31-94 ....*/
- /* This routine takes the pixel data for one row of a 24 */
- /* bit/pixel image and accumulates data in the 32x32x32 R-G-B */
- /* histogram 'vhist'. The pixel data is sent in the 'byte_buf'*/
- /* array. The number of pixels in the array is defined by */
- /* 'width'. */
- /*.............................................................*/
- void analyze_row(byte_buf,width,vhist)
- unsigned char far *byte_buf,far *vhist;
- int width;
- {
- unsigned sum,i;
- for(i=0;i<width;i++)
- {
- sum = 0;
- sum += (byte_buf[3*i+2])/8 << 10; /* RED */
- sum += (byte_buf[3*i+1])/8 << 5; /* GREEN */
- sum += (byte_buf[3*i] )/8; /* BLUE */
- if(vhist[sum] != 255)
- vhist[sum]++;
- }
- return;
- } /*..... End analyze_row ......*/
-
-
- /*........................ BISECT_CUBE ............ 6-1-94 ....*/
- /* Input cube in 'cube', output two cubes in 'cube' and */
- /* 'new_cube'. Cubes are split along longest axis. New cube */
- /* guaranteed to be "validated". */
- /*.............................................................*/
- void bisect_cube(struct CUBE *pcube,struct CUBE *pnew_cube)
- {
- unsigned dx,dy,dz;
- validate_cube(pcube);
- /*.............................................................*/
- /* Get red, green, and blue extent of cube. */
- /*.............................................................*/
- dx = pcube->x1-pcube->x0; /* RED dimension */
- dy = pcube->y1-pcube->y0; /* GREEN dimension */
- dz = pcube->z1-pcube->z0; /* BLUE dimension */
- /*.............................................................*/
- /* If red is longest dimension, split red axis of cube. */
- /*.............................................................*/
- if((dx >= dy) && (dx >= dz))
- {
- pnew_cube->x0 = (pcube->x1 + pcube->x0)/2;
- pnew_cube->y0 = pcube->y0;
- pnew_cube->z0 = pcube->z0;
- pnew_cube->x1 = pcube->x1;
- pnew_cube->y1 = pcube->y1;
- pnew_cube->z1 = pcube->z1;
- pcube->x1 = pnew_cube->x0;
- return;
- }
- /*.............................................................*/
- /* If green is longest dimension, split green axis of cube. */
- /*.............................................................*/
- if((dy >= dx) && (dy >= dz))
- {
- pnew_cube->x0 = pcube->x0;
- pnew_cube->y0 = (pcube->y1 + pcube->y0)/2;
- pnew_cube->z0 = pcube->z0;
- pnew_cube->x1 = pcube->x1;
- pnew_cube->y1 = pcube->y1;
- pnew_cube->z1 = pcube->z1;
- pcube->y1 = pnew_cube->y0;
- return;
- }
- /*.............................................................*/
- /* If blue is longest dimension, split blue axis of cube. */
- /*.............................................................*/
- if((dz >= dx) && (dz >= dy))
- {
- pnew_cube->x0 = pcube->x0;
- pnew_cube->y0 = pcube->y0;
- pnew_cube->z0 = (pcube->z1 + pcube->z0)/2;
- pnew_cube->x1 = pcube->x1;
- pnew_cube->y1 = pcube->y1;
- pnew_cube->z1 = pcube->z1;
- pcube->z1 = pnew_cube->z0;
- return;
- }
- } /*.... END: bisect_cube .....*/
-
-
- /*................. GEN_CUBE_COLOR_STATS ........... 6-1-94 ...*/
- /* Compute cube's color statistics (Volume, Frequency Sum, */
- /* Average Color value for Red, Green, and Blue, Color Error, */
- /* and Figure-Of-Merit). The color error is the sum of */
- /* ABS(color - avg_color)*frequency (sort of) for each color */
- /* in cube. */
- /*.............................................................*/
- void gen_cube_color_stats(struct CUBE *pcube,
- unsigned char *array,int mode)
- {
- unsigned i,j,k,freq;
- int dr,dg,db;
- unsigned long sum,index,index0,color_error;
- long red_avg,grn_avg,blu_avg;
- sum = 0;
- red_avg = 0;
- grn_avg = 0;
- blu_avg = 0;
- color_error = 0;
- /*.............................................................*/
- /* Compute cube's volume */
- /*.............................................................*/
- pcube->vol = (pcube->x1-pcube->x0)*
- (pcube->y1-pcube->y0)*
- (pcube->z1-pcube->z0);
- /*.............................................................*/
- /* Compute average red, green and blue values. */
- /*.............................................................*/
- for(k=pcube->x0;k<pcube->x1;k++)
- {
- index0 = k<<10;
- for(j=pcube->y0;j<pcube->y1;j++)
- {
- index = index0 + (j<<5) + pcube->z0;
- for(i=pcube->z0;i<pcube->z1;i++)
- {
- freq = array[index];
- red_avg += k*freq;
- grn_avg += j*freq;
- blu_avg += i*freq;
- sum += freq;
- index ++;
- }
- }
- }
- if(sum != 0)
- {
- red_avg /= sum;
- grn_avg /= sum;
- blu_avg /= sum;
- }
- else
- {
- red_avg = 0;
- grn_avg = 0;
- blu_avg = 0;
- }
- /*.............................................................*/
- /* Now compute color error. */
- /*.............................................................*/
- for(k=pcube->x0;k<pcube->x1;k++)
- {
- index0 = k<<10;
- for(j=pcube->y0;j<pcube->y1;j++)
- {
- index = index0 + (j<<5) + pcube->z0;
- for(i=pcube->z0;i<pcube->z1;i++)
- {
- freq = array[index];
- dr = (red_avg-(int)k);
- dg = (grn_avg-(int)j);
- db = (blu_avg-(int)i);
- color_error += freq*sqrt(dr*dr+dg*dg+db*db);
- index ++;
- }
- }
- }
- pcube->r_avg = red_avg;
- pcube->g_avg = grn_avg;
- pcube->b_avg = blu_avg;
- pcube->fsum = sum;
- pcube->cerr = color_error;
- /*.............................................................*/
- /* You can decide what characteristic is used for the Figure of*/
- /* Merit (FOM) by setting 'mode' to 1 - 5. Modes 1 and 2 are */
- /* normally used. Modes 3, 4, and 5 are for play. */
- /*.............................................................*/
- if(mode == 1)
- pcube->fom = (float) pcube->vol;
- if(mode == 2)
- pcube->fom = (float) pcube->cerr;
- if(mode == 3)
- pcube->fom = (float) pcube->fsum;
- if(mode == 4)
- pcube->fom = (float)(pcube->cerr)*(float)(pcube->fsum);
- if(mode >= 5)
- pcube->fom = (float)(pcube->vol-1)*(float)(pcube->fsum);
- return;
- } /*.... END: gen_cube_color_stats ....*/
-
-
- /*.................. MOVE_CUBES_TO_LUT ............ 6-3-94 ....*/
- /* This routine loads 'color_array' with the colors of the */
- /* cubes in the 'CUBE_LIST' (after the 'CUBE_LIST' has been */
- /* generated). The return value is the number of colors */
- /* loaded into 'color_array', and is always 256. */
- /*.............................................................*/
- int move_cubes_to_lut(int num_cubes,unsigned char *array,
- unsigned char *color_array)
- {
- unsigned i;
- /*.............................................................*/
- /* Compute Color Lookup Table entries. You could do this by */
- /* taking average of each color component axis of cube. But */
- /* instead ... Use the Average color computed earlier for each */
- /* cube! (This is more accurate color). Multiply by two to */
- /* scale the 5 bit color into the 6 bit palette entry. */
- /*.............................................................*/
- for(i=0;i < num_cubes;i++)
- {
- color_array[3*i+0] = 2*CUBE_LIST[i].r_avg;
- color_array[3*i+1] = 2*CUBE_LIST[i].g_avg;
- color_array[3*i+2] = 2*CUBE_LIST[i].b_avg;
- }
- /*.............................................................*/
- /* Set unused palette entries to black. */
- /*.............................................................*/
- for(i=num_cubes;i<256;i++)
- {
- color_array[3*i+0] = 0;
- color_array[3*i+1] = 0;
- color_array[3*i+2] = 0;
- }
- assign_lut_to_colors(array,num_cubes);
- return 256;
- } /*..... End move_cubes_to_lut ......*/
-
-
- /*................. ASSIGN_LUT_TO_COLORS ........... 6-3-94 ...*/
- /* Assign each of the 32768 color values in the RGB Color Space*/
- /* (compressed from 16M) to one of the up to 256 cubes (which */
- /* map to the color lut). 'ADPTV_ASSIGN_MODE' determines the */
- /* way that colors are assigned. If '0', then color error is */
- /* minimized. Otherwise, all colors which land within a cube */
- /* get set to cube average color. */
- /*.............................................................*/
- void assign_lut_to_colors(unsigned char *array,unsigned
- num_cubes)
- {
- int red,grn,blu,dr,dg,db,error,last_error;
- unsigned i,j,k,n;
- long index,index0;
- if(!ADPTV_ASSIGN_MODE)
- /*.............................................................*/
- /* For each color in the image, assign it the CUBE ID for the */
- /* CUBE which has the nearest average color value . */
- /*.............................................................*/
- {
- for(i=0;i<32768;i++)
- {
- if(array[i] != 0)
- {
- red = (i & 0x7c00) >> 10;
- grn = (i & 0x03e0) >> 5;
- blu = i & 0x001f ;
- last_error = 10000;
- for(n=0;n<num_cubes;n++)
- {
- dr = CUBE_LIST[n].r_avg - red;
- dg = CUBE_LIST[n].g_avg - grn;
- db = CUBE_LIST[n].b_avg - blu;
- error = dr*dr+dg*dg+db*db;
- if(error <= last_error)
- {
- array[i] = n;
- last_error = error;
- }
- }
- }
- }
- }
- /*.............................................................*/
- /* For each cube, assign its ID to all of the colors in */
- /* its boundary. This method is not as accurate as the one */
- /* above but its faster. */
- /*.............................................................*/
- else
- {
- for(n=0;n<num_cubes;n++)
- {
- for(k=CUBE_LIST[n].x0;k<CUBE_LIST[n].x1;k++)
- {
- index0 = k<<10;
- for(j=CUBE_LIST[n].y0;j<CUBE_LIST[n].y1;j++)
- {
- index = index0 + (j<<5) + CUBE_LIST[n].z0;
- for(i=CUBE_LIST[n].z0;i<CUBE_LIST[n].z1;i++)
- {
- array[index] = n;
- index ++;
- }
- }
- }
- }
- }
- return;
- } /*.... END: assign_lut_to_colors ....*/
-
-
- /*..................... VALIDATE_CUBE ............ 1-12-94 ....*/
- /* Insures that cube point 0 is closer to (or same distance */
- /* from) origin of RGB Color than cube point 1. */
- /*.............................................................*/
- void validate_cube(struct CUBE *pcube)
- {
- unsigned temp;
- if(pcube->x0 > pcube->x1)
- {
- temp = pcube->x0;
- pcube->x0 = pcube->x1;
- pcube->x1 = temp;
- }
- if(pcube->y0 > pcube->y1)
- {
- temp = pcube->y0;
- pcube->y0 = pcube->y1;
- pcube->y1 = temp;
- }
- if(pcube->z0 > pcube->z1)
- {
- temp = pcube->z0;
- pcube->z0 = pcube->z1;
- pcube->z1 = temp;
- }
- return;
- } /*.... END: validate_cube ...*/
-
- /*........................... COPY_CUBE .......... 1-15-94 ....*/
- /* This routine copies the 'cube' struct to the 'new_cube' */
- /* struct. */
- /*.............................................................*/
- void copy_cube(struct CUBE cube,struct CUBE *pnew_cube)
- {
- pnew_cube->x0 = cube.x0;
- pnew_cube->y0 = cube.y0;
- pnew_cube->z0 = cube.z0;
- pnew_cube->x1 = cube.x1;
- pnew_cube->y1 = cube.y1;
- pnew_cube->z1 = cube.z1;
- pnew_cube->vol = cube.vol;
- pnew_cube->r_avg = cube.r_avg;
- pnew_cube->g_avg = cube.g_avg;
- pnew_cube->b_avg = cube.b_avg;
- pnew_cube->fsum = cube.fsum;
- pnew_cube->cerr = cube.cerr;
- pnew_cube->fom = cube.fom;
- return;
- } /*.... END: copy_cube ....*/
-
-
- /*..................... ADD_CUBE_TO_LIST ........... 6-1-94 ...*/
- /* Adds a cube to list. Inserts cube appropriately to maintain*/
- /* a descending cube sort based on CUBE_LIST[i].fom. In */
- /* otherwords, CUBE_LIST[0].fom is always going to be the */
- /* largest value of all cubes. Give this routine a cube and */
- /* the current number of cubes in the list 'n'. Routine returns*/
- /* the new value of 'n'. NOTE: For n cubes, you have */
- /* CUBE_LIST[0] thru CUBE_LIST[n-1]. */
- /*.............................................................*/
- int add_cube_to_list(struct CUBE new_cube,int n)
- {
- int m;
- m = n+1;
- /*.............................................................*/
- /* Bump lower FOM valued cubes down a step in cube list. */
- /*.............................................................*/
- if(n>0)
- while(CUBE_LIST[n-1].fom <= new_cube.fom)
- {
- CUBE_LIST[n].x0 = CUBE_LIST[n-1].x0;
- CUBE_LIST[n].y0 = CUBE_LIST[n-1].y0;
- CUBE_LIST[n].z0 = CUBE_LIST[n-1].z0;
- CUBE_LIST[n].x1 = CUBE_LIST[n-1].x1;
- CUBE_LIST[n].y1 = CUBE_LIST[n-1].y1;
- CUBE_LIST[n].z1 = CUBE_LIST[n-1].z1;
- CUBE_LIST[n].vol = CUBE_LIST[n-1].vol;
- CUBE_LIST[n].r_avg = CUBE_LIST[n-1].r_avg;
- CUBE_LIST[n].g_avg = CUBE_LIST[n-1].g_avg;
- CUBE_LIST[n].b_avg = CUBE_LIST[n-1].b_avg;
- CUBE_LIST[n].fsum = CUBE_LIST[n-1].fsum;
- CUBE_LIST[n].cerr = CUBE_LIST[n-1].cerr;
- CUBE_LIST[n].fom = CUBE_LIST[n-1].fom;
- n--;
- if(n==0) break;
- }
- /*.............................................................*/
- /* Add new cube to cube list. */
- /*.............................................................*/
- CUBE_LIST[n].x0 = new_cube.x0;
- CUBE_LIST[n].y0 = new_cube.y0;
- CUBE_LIST[n].z0 = new_cube.z0;
- CUBE_LIST[n].x1 = new_cube.x1;
- CUBE_LIST[n].y1 = new_cube.y1;
- CUBE_LIST[n].z1 = new_cube.z1;
- CUBE_LIST[n].vol = new_cube.vol;
- CUBE_LIST[n].r_avg = new_cube.r_avg;
- CUBE_LIST[n].g_avg = new_cube.g_avg;
- CUBE_LIST[n].b_avg = new_cube.b_avg;
- CUBE_LIST[n].fsum = new_cube.fsum;
- CUBE_LIST[n].cerr = new_cube.cerr;
- CUBE_LIST[n].fom = new_cube.fom;
- return m;
- } /*.. END: add_cube_to_list ..*/
-
-
- /*................... DELETE_CUBE_FROM_LIST ...... 1-15-94 ....*/
- /* Deletes cube 'p' from cube list. Bumps up remaining cubes to*/
- /* keep list consecutive and hole free. Give this routine the */
- /* current number of cubes in list ('n') and the cube id to be */
- /* deleted ('p'). Routine returns the new value of 'n'. */
- /* NOTE: For n cubes, you have CUBE_LIST[0] thru CUBE_LIST[n-1]*/
- /*.............................................................*/
- int delete_cube_from_list(int p,int n)
- {
- if(p >= n)
- return n;
- while(p < n-1)
- {
- CUBE_LIST[p].x0 = CUBE_LIST[p+1].x0;
- CUBE_LIST[p].y0 = CUBE_LIST[p+1].y0;
- CUBE_LIST[p].z0 = CUBE_LIST[p+1].z0;
- CUBE_LIST[p].x1 = CUBE_LIST[p+1].x1;
- CUBE_LIST[p].y1 = CUBE_LIST[p+1].y1;
- CUBE_LIST[p].z1 = CUBE_LIST[p+1].z1;
- CUBE_LIST[p].vol = CUBE_LIST[p+1].vol;
- CUBE_LIST[p].r_avg = CUBE_LIST[p+1].r_avg;
- CUBE_LIST[p].g_avg = CUBE_LIST[p+1].g_avg;
- CUBE_LIST[p].b_avg = CUBE_LIST[p+1].b_avg;
- CUBE_LIST[p].fsum = CUBE_LIST[p+1].fsum;
- CUBE_LIST[p].cerr = CUBE_LIST[p+1].cerr;
- CUBE_LIST[p].fom = CUBE_LIST[p+1].fom;
- p++;
- }
- return n-1;
- } /*.. END: delete_cube_from_list ..*/
-
- /*..................... REPLACE_PIXEL.C ............ 6-1-94 ...*/
- /* This routine compresses the 3 byte per pixel data in the */
- /* array 'byte_buf' into a single byte per pixel data array */
- /* (back into 'byte_buf'). The 8-8-8 RGB pixel is down */
- /* converted to a 5-5-5 RGB pixel. Then, the 15 bit RGB */
- /* pixel value is used to look up in the 'array' to get the 8 */
- /* bit palette index for that color. The number of pixels in */
- /* 'byte_buf' is defined by 'width'. */
- /*.............................................................*/
- void replace_pixel(unsigned char *byte_buf,unsigned
- width,unsigned char *array)
- {
- int i,sum;
- /*.............................................................*/
- /* If Adaptive Palette ON, map pixel to adaptive palette. */
- /*.............................................................*/
- if(ADPTV_MODE)
- for(i=0;i<width;i++)
- {
- sum = 0;
- sum += (byte_buf[3*i+2])/8 << 10; /* RED */
- sum += (byte_buf[3*i+1])/8 << 5; /* GREEN */
- sum += (byte_buf[3*i] )/8; /* BLUE */
- byte_buf[i] = array[sum];
- }
- /*.............................................................*/
- /* If Adaptive Palette OFF, map pixel to 8 bit RGB palette. */
- /*.............................................................*/
- else
- for(i=0;i<width;i++)
- {
- sum = 0;
- sum += (byte_buf[3*i+2])/32 << 5; /* RED */
- sum += (byte_buf[3*i+1])/32 << 2; /* GREEN */
- sum += (byte_buf[3*i] )/64; /* BLUE */
- byte_buf[i] = (unsigned char) sum;
- }
- return;
- } /*..... End replace_pixel ......*/
-
-
-
- /*................ SET_ADAPTIVE_CONFIG ........... 4-30-94 ....*/
- /* This routine configures the operation of the TIFF256 library*/
- /* with regards to 24 bit/pixel images. The input parameters */
- /* have are: */
- /* */
- /* enable - Adaptive Palette is enabled when enable */
- /* is 1. disabled otherwise. */
- /* num_colors - This parameter determines how many colors */
- /* the 16M color image will be reduced to. */
- /* (2 min, 256 max!) */
- /* quality - This parameter lets the user optimize the */
- /* Adaptive Palette algorithm for image */
- /* quality. The valid range is from 0 to 100.*/
- /* For values closer to 0, the algorithm is*/
- /* optimized for images with fewer colors, */
- /* but many shades per color (smooth shading */
- /* is emphasized at the expense of color */
- /* variety). */
- /* For values closer to 100, the algorithm */
- /* is optimized for images with a broader */
- /* color distribution (many colors are */
- /* accomodated at the expense of shade */
- /* continuity). */
- /*.............................................................*/
- void set_adaptive_config(int enable,int num_colors,int quality)
- {
- ADPTV_MODE = enable;
- ADPTV_NUM_COLORS = num_colors;
- ADPTV_QUALITY = quality;
- if(ADPTV_NUM_COLORS > 256) ADPTV_NUM_COLORS = 256;
- if(ADPTV_NUM_COLORS < 2) ADPTV_NUM_COLORS = 2;
- if(ADPTV_QUALITY > 100) ADPTV_QUALITY = 100;
- return;
- }
-
- /*................. GET_ADAPTIVE_CONFIG ............ 4-10-94 ..*/
- /* This routine returns the current Adaptive Palette */
- /* configuration parameters (which were set by */
- /* set_adaptive_config(). */
- /*.............................................................*/
- void get_adaptive_config(int *penable,int *pnum_colors,
- int *pquality)
- {
- *penable = ADPTV_MODE;
- *pnum_colors = ADPTV_NUM_COLORS;
- *pquality = ADPTV_QUALITY;
- return;
- }
-
- /*.................... TRUE_COLOR_LUT.C .......... 5-15-94 ....*/
- /* This routine generates a 'true color' LUT. An 8 bit index */
- /* into the LUT represents 3 bits of RED, 3 bits of GREEN, and */
- /* 2 bits of BLUE. The 3 msbs of the 8 bit index are the RED */
- /* field, next 3 are GREEN, and the 2 lsbs are the BLUE field. */
- /* */
- /*.............................................................*/
- void true_color_lut(void)
- {
- int i;
- unsigned char color_array[768];
- for(i=0;i<256;i++)
- {
- color_array[3*i+0]= ((i & 0x00e0) >> 5) * 9;
- color_array[3*i+1]= ((i & 0x001c) >> 2) * 9;
- color_array[3*i+2]= (i & 0x0003) * 21;
- }
- vsa_write_color_block(0,256,color_array);
- return;
- } /*..... End true_color_lut .....*/
-